

#include "XmlTree.h"
#include "XmlUtil.h"
#include <queue>


#define GETNODESUBELEMENT(node, filter, listOfElements)	\
  if( node->getAttributes() ) \
    for(unsigned i=0;i<node->getAttributes()->getLength(); \
	i++) \
      listOfElements.push(node->getAttributes()->item(i)); \
  for(DOMNode* curr=node->getFirstChild();curr;) \
    { \
      if(filter.acceptNode(curr)==DOMWriterFilter::FILTER_ACCEPT) \
	listOfElements.push(curr); \
      curr=curr->getNextSibling(); \
    }

static const awa::IndexParserOptions ParserSupportedFeatures[] = 
  {
    awa::VALIDATION,
    awa:: DOMNAMESPACES,
    awa::SCHEMA,
    awa::SCHEMAFULLCHECKING,
    awa::DATATYPENORMALIZATION,
    awa::CACHEGRAMMARFROMPARSE
  };

std::vector<awa::IndexParserOptions> 
awa::getParserSupportedFeatures() {
  return std::vector<awa::IndexParserOptions>(ParserSupportedFeatures,
					      ( ParserSupportedFeatures + sizeof(ParserSupportedFeatures)/sizeof(awa::IndexParserOptions)) );

}

const XMLCh* 
awa::MapToXercesParserOptions( IndexParserOptions ind) {
  
  switch( ind ) {
  case VALIDATION: 
    return XMLUni::fgDOMValidation;
  case DOMNAMESPACES: 
    return XMLUni::fgDOMNamespaces;
  case SCHEMA:
    return XMLUni::fgXercesSchema;
  case SCHEMAFULLCHECKING: 
    return XMLUni::fgXercesSchemaFullChecking;
  case DATATYPENORMALIZATION:
    return XMLUni::fgDOMDatatypeNormalization;
  case CACHEGRAMMARFROMPARSE:
    return XMLUni::fgXercesCacheGrammarFromParse;
  default:
    return NULL;
  }
}


short
awa::XercesNodeFilter::acceptNode(const DOMNode* node) const {
  
  if(opts == SHOW_ALL)
    return FILTER_ACCEPT; 
  
  return ( (*Filters)[node->getNodeType()] & opts) 
    ? FILTER_ACCEPT
    : FILTER_REJECT;
  
}


std::map<awa::XercesNodeFilter::NodeType, awa::XercesNodeFilter::FilterRule> mkFiltersTable() {
  
  awa::XercesNodeFilter::NodeType types[12] = { 
    DOMNode::ELEMENT_NODE, 
    DOMNode::ATTRIBUTE_NODE, 
    DOMNode::TEXT_NODE, 
    DOMNode::CDATA_SECTION_NODE, 
    DOMNode::ENTITY_REFERENCE_NODE, 
    DOMNode::ENTITY_NODE, 
    DOMNode::PROCESSING_INSTRUCTION_NODE,
    DOMNode::COMMENT_NODE, 
    DOMNode::DOCUMENT_NODE, 
    DOMNode::DOCUMENT_TYPE_NODE, 
    DOMNode::DOCUMENT_FRAGMENT_NODE,
    DOMNode::NOTATION_NODE };
  
  awa::XercesNodeFilter::FilterRule rules[13] = {
    SHOW_ELEMENT, 
    SHOW_TEXT, 
    SHOW_ATTRIBUTE,
    SHOW_CDATA_SECTION, 
    SHOW_ENTITY_REFERENCE, 
    SHOW_ENTITY, 
    SHOW_PROCESSING_INSTRUCTION, 
    SHOW_COMMENT, 
    SHOW_DOCUMENT,
    SHOW_DOCUMENT_TYPE, 
    SHOW_DOCUMENT_FRAGMENT, 
    SHOW_NOTATION,
    SHOW_ALL };
  
  std::map<awa::XercesNodeFilter::NodeType, awa::XercesNodeFilter::FilterRule> table;
  for(int i = 0; i < 12; i++)
    table.insert( std::map<awa::XercesNodeFilter::NodeType, awa::XercesNodeFilter::FilterRule>::value_type(types[i], rules[i]) );
  
  return table;
}

awa::XercesNodeFilter::FilterLookupTable 
awa::XercesNodeFilter::Filters = awa::XercesNodeFilter::FilterLookupTable(new std::map<awa::XercesNodeFilter::NodeType, awa::XercesNodeFilter::FilterRule>( mkFiltersTable() ) );



awa::AbstractTree* awa::copyDOM(DOMNode* node, awa::XercesNodeFilter filter) {

  assert( node != NULL );

  if( filter.acceptNode( node ) != DOMWriterFilter::FILTER_ACCEPT )
    throw awa::XercesException( DOMException::NOT_SUPPORTED_ERR, 
				*StrtoX("Empty Tree"),
				__FILE__,
				__LINE__ );
  
  awa::AbstractTree* STLTree(new awa::AbstractTree( node )) ;

  awa::AbstractTree::level_order_node_iterator currNode;
  currNode = STLTree->level_order_node_begin();
  
  do {
    
    std::queue<DOMNode*> subElements;
    GETNODESUBELEMENT(currNode->pre_order_begin()->ptrDOMNode, 
		   filter, 
		   subElements)
      while( subElements.size() )
	{
	  if(filter.acceptNode(subElements.front()) == DOMWriterFilter::FILTER_ACCEPT) \
	    currNode->insert( subElements.front() );
	  subElements.pop();
	}
    
  }while( ++currNode != STLTree->level_order_node_end());
  
  return STLTree;
}

